﻿using Newtonsoft.Json.Linq;
using System.Data;

/// <summary>
/// 
/// </summary>
public static class DataDb
{
    /// <summary>
    /// 
    /// </summary>
    /// <param name="dbDataType"></param>
    /// <returns></returns>
    /// <exception cref="ArgumentException"></exception>
    public static DbType MapDbType(this string dbDataType)
    {
        switch (dbDataType.ToLower())
        {
            case "int":
            case "integer":
            case "smallint":
            case "bigint":
                return DbType.Int32;
            case "decimal":
            case "numeric":
            case "money":
                return DbType.Decimal;
            case "float":
            case "real":
                return DbType.Single;
            case "double":
            case "double precision":
                return DbType.Double;
            case "varchar":
            case "nvarchar":
            case "char":
            case "nchar":
            case "text":
            case "clob":
                return DbType.String;
            case "datetime":
            case "timestamp":
            case "date":
            case "time":
            case "datetime2":
            case "datetimeoffset":
                return DbType.DateTime;
            case "bit":
                return DbType.Boolean;
            case "binary":
            case "varbinary":
            case "blob":
                return DbType.Binary;
            case "uniqueidentifier":
                return DbType.Guid;
            default:
                throw new ArgumentException($"不支持的数据库类型: {dbDataType}");
        }
    }
    /// <summary>
    /// 
    /// </summary>
    /// <param name="dbType"></param>
    /// <param name="value"></param>
    /// <returns></returns>
    /// <exception cref="ArgumentException"></exception>
    public static bool IsValueOfType(this DbType dbType, ref JToken value)
    {
        switch (dbType)
        {
            case DbType.Int32:
                return value.Type == JTokenType.Integer;
            case DbType.Decimal:
                return value.Type == JTokenType.Float || value.Type == JTokenType.Integer;
            case DbType.Single:
                return value.Type == JTokenType.Float;
            case DbType.Double:
                return value.Type == JTokenType.Float;
            case DbType.String:
                return value.Type == JTokenType.String;
            case DbType.DateTime:
                if (value.Type == JTokenType.Date)
                    return true;
                else if (value.Type == JTokenType.String)
                {
                    DateTime dateTime;
                    if (DateTime.TryParse(value.ToString(), out dateTime))
                    {
                        value = new JValue(dateTime);
                        return true;
                    }
                    return false;
                }
                return false;
            case DbType.Boolean:
                if (value.Type == JTokenType.Boolean)
                    return (bool)value == true || (bool)value == false; // This is always true for Boolean tokens
                else if (value.Type == JTokenType.Integer)
                    return (int)value == 0 || (int)value == 1;
                return false;
            case DbType.Binary:
                return value.Type == JTokenType.Bytes;
            case DbType.Guid:
                return value.Type == JTokenType.String && Guid.TryParse(value.ToString(), out _);
            default:
                throw new ArgumentException($"不支持的数据库类型: {dbType}");
        }
    }

    static List<string> _systemReserveds = new List<string> { "id", "createtime", "modifytime" };

    /// <summary>
    /// 
    /// </summary>
    /// <param name="dbColumnName"></param>
    /// <param name="value"></param>
    /// <returns></returns>
    public static bool SetReservedValue(string dbColumnName, out JToken? value)
    {
        value = null;

        if (dbColumnName.IsNullOrWhiteSpace())
            return false;

        if (_systemReserveds.Contains(dbColumnName))
        {
            switch (dbColumnName.ToLower())
            {
                case "id":
                    value = new JValue(IdGenerator.Id);
                    return false;
                case "createtime":
                    value = new JValue(DateTime.Now);
                    return false;
                case "modifytime":
                    value = new JValue(DateTime.Now);
                    return false;
                default:
                    return false;
            }
        }
        return false;
    }
}
